home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  58.7 KB  |  1,959 lines

  1. /* $Id: draw.c,v 1.18 1997/03/08 02:02:52 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.2
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: draw.c,v $
  26.  * Revision 1.18  1997/03/08 02:02:52  brianp
  27.  * vertex_feedback() didn't save the current normal
  28.  *
  29.  * Revision 1.17  1997/02/15 19:00:02  brianp
  30.  * more robust, but slower, test for zero-area polygons
  31.  *
  32.  * Revision 1.16  1997/02/04 19:40:16  brianp
  33.  * changed size of vlist[] array to VB_SIZE per Randy Frank
  34.  *
  35.  * Revision 1.15  1997/01/28 22:16:08  brianp
  36.  * glBegin() now checks if already inside Begin/End pair
  37.  *
  38.  * Revision 1.14  1996/12/18 20:00:57  brianp
  39.  * gl_set_material() now takes a bitmask instead of face and pname
  40.  *
  41.  * Revision 1.13  1996/12/07 10:20:44  brianp
  42.  * call gl_set_material() instead of gl_Materialfv()
  43.  *
  44.  * Revision 1.12  1996/12/03 20:35:21  brianp
  45.  * copy_vertex() didn't copy clip coordinates, caused line strip clipping bug
  46.  *
  47.  * Revision 1.11  1996/11/09 03:13:12  brianp
  48.  * gl_transform_vb_part2() no longer calls render_vb()
  49.  *
  50.  * Revision 1.10  1996/11/08 02:20:25  brianp
  51.  * new texture coordinate transformation code
  52.  *
  53.  * Revision 1.9  1996/11/04 02:31:19  brianp
  54.  * Viewport.Sx and Viewport.Tx are now multiplied by DEPTH_SCALE
  55.  *
  56.  * Revision 1.8  1996/10/31 01:11:46  brianp
  57.  * minor clean ups
  58.  *
  59.  * Revision 1.7  1996/10/12 18:23:06  brianp
  60.  * window Z coord was incorrectly computed in render_clipped_line()
  61.  *
  62.  * Revision 1.6  1996/10/11 03:44:34  brianp
  63.  * cleaned up the polygon offset code
  64.  *
  65.  * Revision 1.5  1996/09/27 01:26:16  brianp
  66.  * removed unused variables
  67.  *
  68.  * Revision 1.4  1996/09/20 02:55:17  brianp
  69.  * updated profiling code, removed old polygon offset code
  70.  *
  71.  * Revision 1.3  1996/09/15 14:17:30  brianp
  72.  * now use GLframebuffer and GLvisual
  73.  *
  74.  * Revision 1.2  1996/09/15 01:48:58  brianp
  75.  * removed #define NULL 0
  76.  *
  77.  * Revision 1.1  1996/09/13 01:38:16  brianp
  78.  * Initial revision
  79.  *
  80.  */
  81.  
  82.  
  83. /*
  84.  * Draw points, lines, and polygons.
  85.  */
  86.  
  87.  
  88. #ifdef DEBUG
  89. #  include <assert.h>
  90. #endif
  91. #include <math.h>
  92. #include <stdio.h>
  93. #include <stdlib.h>
  94. #include <string.h>
  95. #include "clip.h"
  96. #include "context.h"
  97. #include "draw.h"
  98. #include "feedback.h"
  99. #include "fog.h"
  100. #include "light.h"
  101. #include "lines.h"
  102. #include "dlist.h"
  103. #include "macros.h"
  104. #include "matrix.h"
  105. #include "pb.h"
  106. #include "points.h"
  107. #include "texture.h"
  108. #include "types.h"
  109. #include "vb.h"
  110. #include "xform.h"
  111.  
  112.  
  113.  
  114. #ifdef DEBUG
  115. #  define ASSERT(X)   assert(X)
  116. #else
  117. #  define ASSERT(X)
  118. #endif
  119.  
  120.  
  121.  
  122. #ifdef PROFILE
  123. #  define START_PROFILE                \
  124.     {                    \
  125.        GLdouble t0 = gl_time();
  126.  
  127. #  define END_PROFILE( TIMER, COUNTER, INCR )    \
  128.        TIMER += (gl_time() - t0);        \
  129.        COUNTER += INCR;            \
  130.     }
  131. #else
  132. #  define START_PROFILE
  133. #  define END_PROFILE( TIMER, COUNTER, INCR )
  134. #endif
  135.  
  136.  
  137.  
  138. /*
  139.  * Check if the global material has to be updated with info that was
  140.  * associated with a vertex via glMaterial.
  141.  */
  142. static void update_material( GLcontext *ctx, GLuint i )
  143. {
  144.    struct vertex_buffer *VB = ctx->VB;
  145.  
  146.    if (VB->MaterialMask[i]) {
  147.       if (VB->MaterialMask[i] & FRONT_AMBIENT_BIT) {
  148.          COPY_4V( ctx->Light.Material[0].Ambient, VB->Material[i][0].Ambient );
  149.       }
  150.       if (VB->MaterialMask[i] & BACK_AMBIENT_BIT) {
  151.          COPY_4V( ctx->Light.Material[1].Ambient, VB->Material[i][1].Ambient );
  152.       }
  153.       if (VB->MaterialMask[i] & FRONT_DIFFUSE_BIT) {
  154.          COPY_4V( ctx->Light.Material[0].Diffuse, VB->Material[i][0].Diffuse );
  155.       }
  156.       if (VB->MaterialMask[i] & BACK_DIFFUSE_BIT) {
  157.          COPY_4V( ctx->Light.Material[1].Diffuse, VB->Material[i][1].Diffuse );
  158.       }
  159.       if (VB->MaterialMask[i] & FRONT_SPECULAR_BIT) {
  160.          COPY_4V( ctx->Light.Material[0].Specular, VB->Material[i][0].Specular );
  161.       }
  162.       if (VB->MaterialMask[i] & BACK_SPECULAR_BIT) {
  163.          COPY_4V( ctx->Light.Material[1].Specular, VB->Material[i][1].Specular );
  164.       }
  165.       if (VB->MaterialMask[i] & FRONT_EMISSION_BIT) {
  166.          COPY_4V( ctx->Light.Material[0].Emission, VB->Material[i][0].Emission );
  167.       }
  168.       if (VB->MaterialMask[i] & BACK_EMISSION_BIT) {
  169.          COPY_4V( ctx->Light.Material[1].Emission, VB->Material[i][1].Emission );
  170.       }
  171.       if (VB->MaterialMask[i] & FRONT_SHININESS_BIT) {
  172.          ctx->Light.Material[0].Shininess = VB->Material[i][0].Shininess;
  173.       }
  174.       if (VB->MaterialMask[i] & BACK_SHININESS_BIT) {
  175.          ctx->Light.Material[1].Shininess = VB->Material[i][1].Shininess;
  176.       }
  177.       if (VB->MaterialMask[i] & FRONT_INDEXES_BIT) {
  178.          ctx->Light.Material[0].AmbientIndex = VB->Material[i][0].AmbientIndex;
  179.          ctx->Light.Material[0].DiffuseIndex = VB->Material[i][0].DiffuseIndex;
  180.          ctx->Light.Material[0].SpecularIndex = VB->Material[i][0].SpecularIndex;
  181.       }
  182.       if (VB->MaterialMask[i] & BACK_INDEXES_BIT) {
  183.          ctx->Light.Material[1].AmbientIndex = VB->Material[i][1].AmbientIndex;
  184.          ctx->Light.Material[1].DiffuseIndex = VB->Material[i][1].DiffuseIndex;
  185.          ctx->Light.Material[1].SpecularIndex = VB->Material[i][1].SpecularIndex;
  186.       }
  187.       VB->MaterialMask[i] = 0;  /* reset now */
  188.    }
  189. }
  190.  
  191.  
  192.  
  193. /*
  194.  * Render a line segment from VB[v1] to VB[v2] when either one or both
  195.  * endpoints must be clipped.
  196.  */
  197. static void render_clipped_line( GLcontext *ctx, GLuint v1, GLuint v2 )
  198. {
  199.    GLfloat d;
  200.    GLfloat ndc_x, ndc_y, ndc_z;
  201.    GLuint provoking_vertex;
  202.    struct vertex_buffer *VB = ctx->VB;
  203.  
  204.    /* which vertex dictates the color when flat shading: */
  205.    provoking_vertex = v2;
  206.  
  207.    /*
  208.     * Clipping may introduce new vertices.  New vertices will be stored
  209.     * in the vertex buffer arrays starting with location VB->Free.  After
  210.     * we've rendered the line, these extra vertices can be overwritten.
  211.     */
  212.    VB->Free = VB_MAX;
  213.  
  214.    /* Clip against user clipping planes */
  215.    if (ctx->Transform.AnyClip) {
  216.       GLuint orig_v1 = v1, orig_v2 = v2;
  217.       if (gl_userclip_line( ctx, &v1, &v2 )==0)
  218.     return;
  219.       /* Apply projection matrix:  clip = Proj * eye */
  220.       if (v1!=orig_v1) {
  221.          TRANSFORM_POINT( VB->Clip[v1], ctx->ProjectionMatrix, VB->Eye[v1] );
  222.       }
  223.       if (v2!=orig_v2) {
  224.          TRANSFORM_POINT( VB->Clip[v2], ctx->ProjectionMatrix, VB->Eye[v2] );
  225.       }
  226.    }
  227.  
  228.    /* Clip against view volume */
  229.    if (gl_viewclip_line( ctx, &v1, &v2 )==0)
  230.       return;
  231.  
  232.    /* Transform from clip coords to ndc:  ndc = clip / W */
  233.    ASSERT( VB->Clip[v1][3] != 0.0 );
  234.    d = 1.0F / VB->Clip[v1][3];
  235.    ndc_x = VB->Clip[v1][0] * d;
  236.    ndc_y = VB->Clip[v1][1] * d;
  237.    ndc_z = VB->Clip[v1][2] * d;
  238.  
  239.    /* Map ndc coord to window coords. */
  240.    VB->Win[v1][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx;
  241.    VB->Win[v1][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty;
  242.    VB->Win[v1][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz;
  243.  
  244.    /* Transform from clip coords to ndc:  ndc = clip / W */
  245.    ASSERT( VB->Clip[v2][3] != 0.0 );
  246.    d = 1.0F / VB->Clip[v2][3];
  247.    ndc_x = VB->Clip[v2][0] * d;
  248.    ndc_y = VB->Clip[v2][1] * d;
  249.    ndc_z = VB->Clip[v2][2] * d;
  250.  
  251.    /* Map ndc coord to window coords. */
  252.    VB->Win[v2][0] = ndc_x * ctx->Viewport.Sx + ctx->Viewport.Tx;
  253.    VB->Win[v2][1] = ndc_y * ctx->Viewport.Sy + ctx->Viewport.Ty;
  254.    VB->Win[v2][2] = ndc_z * ctx->Viewport.Sz + ctx->Viewport.Tz;
  255.  
  256.    START_PROFILE
  257.    (*ctx->LineFunc)( ctx, v1, v2, provoking_vertex );
  258.    END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  259. }
  260.  
  261.  
  262.  
  263. /*
  264.  * Compute Z offsets for a polygon with plane defined by (A,B,C,D)
  265.  * D is not needed.
  266.  */
  267. static void offset_polygon( GLcontext *ctx, GLfloat a, GLfloat b, GLfloat c )
  268. {
  269.    GLfloat ac, bc, m;
  270.    GLfloat offset;
  271.  
  272.    if (c<0.001F && c>-0.001F) {
  273.       /* to prevent underflow problems */
  274.       offset = 0.0F;
  275.    }
  276.    else {
  277.       ac = a / c;
  278.       bc = b / c;
  279.       if (ac<0.0F)  ac = -ac;
  280.       if (bc<0.0F)  bc = -bc;
  281.       m = MAX2( ac, bc );
  282.       /* m = sqrt( ac*ac + bc*bc ); */
  283.  
  284.       offset = m * ctx->Polygon.OffsetFactor + ctx->Polygon.OffsetUnits;
  285.    }
  286.  
  287.    ctx->PointZoffset   = ctx->Polygon.OffsetPoint ? offset : 0.0F;
  288.    ctx->LineZoffset    = ctx->Polygon.OffsetLine  ? offset : 0.0F;
  289.    ctx->PolygonZoffset = ctx->Polygon.OffsetFill  ? offset : 0.0F;
  290. }
  291.  
  292.  
  293.  
  294. /*
  295.  * When glPolygonMode() is used to specify that the front/back rendering
  296.  * mode for polygons is not GL_FILL we end up calling this function.
  297.  */
  298. static void unfilled_polygon( GLcontext *ctx,
  299.                               GLuint n, GLuint vlist[],
  300.                               GLuint pv, GLuint facing )
  301. {
  302.    GLenum mode = facing ? ctx->Polygon.BackMode : ctx->Polygon.FrontMode;
  303.    struct vertex_buffer *VB = ctx->VB;
  304.  
  305.    if (mode==GL_POINT) {
  306.       GLint i, j;
  307.       GLboolean edge;
  308.  
  309.       if (   ctx->Primitive==GL_TRIANGLES
  310.           || ctx->Primitive==GL_QUADS
  311.           || ctx->Primitive==GL_POLYGON) {
  312.          edge = GL_FALSE;
  313.       }
  314.       else {
  315.          edge = GL_TRUE;
  316.       }
  317.  
  318.       for (i=0;i<n;i++) {
  319.          j = vlist[i];
  320.          if (edge || VB->Edgeflag[j]) {
  321.             (*ctx->PointsFunc)( ctx, j, j );
  322.          }
  323.       }
  324.    }
  325.    else if (mode==GL_LINE) {
  326.       GLuint i, j0, j1;
  327.       GLboolean edge;
  328.  
  329.       ctx->StippleCounter = 0;
  330.  
  331.       if (   ctx->Primitive==GL_TRIANGLES
  332.           || ctx->Primitive==GL_QUADS
  333.           || ctx->Primitive==GL_POLYGON) {
  334.          edge = GL_FALSE;
  335.       }
  336.       else {
  337.          edge = GL_TRUE;
  338.       }
  339.  
  340.       /* draw the edges */
  341.       for (i=0;i<n;i++) {
  342.          j0 = (i==0) ? vlist[n-1] : vlist[i-1];
  343.          j1 = vlist[i];
  344.          if (edge || VB->Edgeflag[j0]) {
  345.             START_PROFILE
  346.             (*ctx->LineFunc)( ctx, j0, j1, pv );
  347.             END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  348.          }
  349.       }
  350.    }
  351.    else {
  352.       /* Fill the polygon */
  353.       GLuint j0, i;
  354.       j0 = vlist[0];
  355.       for (i=2;i<n;i++) {
  356.          START_PROFILE
  357.          (*ctx->TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv );
  358.          END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  359.       }
  360.    }
  361. }
  362.  
  363.  
  364. /*
  365.  * Compute signed area of the n-sided polgyon specified by vertices vb->Win[]
  366.  * and vertex list vlist[].
  367.  * A clockwise polygon will return a negative area.
  368.  * A counter-clockwise polygon will return a positive area.
  369.  */
  370. static GLfloat polygon_area( const struct vertex_buffer *vb,
  371.                              GLuint n, const GLuint vlist[] )
  372. {
  373.    GLfloat area = 0.0F;
  374.    GLint i;
  375.    for (i=0;i<n;i++) {
  376.       /* area = sum of trapezoids */
  377.       GLuint j0 = vlist[i];
  378.       GLuint j1 = vlist[(i+1)%n];
  379.       GLfloat x0 = vb->Win[j0][0];
  380.       GLfloat y0 = vb->Win[j0][1];
  381.       GLfloat x1 = vb->Win[j1][0];
  382.       GLfloat y1 = vb->Win[j1][1];
  383.       GLfloat trapArea = (x0-x1)*(y0+y1);  /* Note: no divide by two here! */
  384.       area += trapArea;
  385.    }
  386.    return area * 0.5F;     /* divide by two now! */
  387. }
  388.  
  389.  
  390. /*
  391.  * Render a polygon in which doesn't have to be clipped.
  392.  * Input:  n - number of vertices
  393.  *         vlist - list of vertices in the polygon.
  394.  *         odd_flag - if non-zero, reverse the orientation of the polygon
  395.  */
  396. static void render_polygon( GLcontext *ctx,
  397.                             GLuint n, GLuint vlist[], GLuint odd_flag )
  398. {
  399.    struct vertex_buffer *VB = ctx->VB;
  400.    GLuint pv;
  401.  
  402.    /* which vertex dictates the color when flat shading: */
  403.    pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1];
  404.  
  405.    /* Compute orientation of polygon, do cull test, offset, etc */
  406.    {
  407.       GLuint facing;   /* 0=front, 1=back */
  408.       GLfloat area = polygon_area( VB, n, vlist );
  409.  
  410.       if (area==0.0F) {
  411.          /* polygon has zero area, don't draw it */
  412.          return;
  413.       }
  414.  
  415.       facing = (area<0.0F) ^ odd_flag ^ (ctx->Polygon.FrontFace==GL_CW);
  416.  
  417.       if ((facing+1) & ctx->Polygon.CullBits) {
  418.          return;   /* culled */
  419.       }
  420.  
  421.       if (ctx->Polygon.OffsetAny) {
  422.          /* compute plane equation of polygon, apply offset */
  423.          GLuint j0 = vlist[0];
  424.          GLuint j1 = vlist[1];
  425.          GLuint j2 = vlist[2];
  426.          GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  427.          GLfloat ex = VB->Win[j1][0] - VB->Win[j3][0];
  428.          GLfloat ey = VB->Win[j1][1] - VB->Win[j3][1];
  429.          GLfloat ez = VB->Win[j1][2] - VB->Win[j3][2];
  430.          GLfloat fx = VB->Win[j2][0] - VB->Win[j0][0];
  431.          GLfloat fy = VB->Win[j2][1] - VB->Win[j0][1];
  432.          GLfloat fz = VB->Win[j2][2] - VB->Win[j0][2];
  433.          GLfloat a = ey*fz-ez*fy;
  434.          GLfloat b = ez*fx-ex*fz;
  435.          GLfloat c = ex*fy-ey*fx;
  436.          offset_polygon( ctx, a, b, c );
  437.       }
  438.  
  439.       if (ctx->Light.Model.TwoSide) {
  440.          if (facing==1 && ctx->Light.Enabled) {
  441.             /* use back color or index */
  442.             VB->Color = VB->Bcolor;
  443.             VB->Index = VB->Bindex;
  444.          }
  445.          else {
  446.             /* use front color or index */
  447.             VB->Color = VB->Fcolor;
  448.             VB->Index = VB->Findex;
  449.          }
  450.       }
  451.  
  452.       /* Render the polygon! */
  453.       if (ctx->Polygon.Unfilled) {
  454.          unfilled_polygon( ctx, n, vlist, pv, facing );
  455.       }
  456.       else {
  457.          /* Draw filled polygon as a triangle fan */
  458.          GLint i;
  459.          GLuint j0 = vlist[0];
  460.          for (i=2;i<n;i++) {
  461.             START_PROFILE
  462.             (*ctx->TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv );
  463.             END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  464.          }
  465.       }
  466.    }
  467. }
  468.  
  469.  
  470.  
  471. /*
  472.  * Render a polygon in which at least one vertex has to be clipped.
  473.  * Input:  n - number of vertices
  474.  *         vlist - list of vertices in the polygon.
  475.  *         odd_flag - if non-zero, reverse the orientation of the polygon
  476.  */
  477. static void render_clipped_polygon( GLcontext *ctx,
  478.                                     GLuint n, GLuint vlist[], GLuint odd_flag )
  479. {
  480.    GLuint pv;
  481.    struct vertex_buffer *VB = ctx->VB;
  482.    GLfloat (*win)[3] = VB->Win;
  483.  
  484.    /* which vertex dictates the color when flat shading: */
  485.    pv = (ctx->Primitive==GL_POLYGON) ? vlist[0] : vlist[n-1];
  486.  
  487.    /*
  488.     * Clipping may introduce new vertices.  New vertices will be stored
  489.     * in the vertex buffer arrays starting with location VB->Free.  After
  490.     * we've rendered the polygon, these extra vertices can be overwritten.
  491.     */
  492.    VB->Free = VB_MAX;
  493.  
  494.    /* Clip against user clipping planes in eye coord space. */
  495.    if (ctx->Transform.AnyClip) {
  496.       GLfloat *proj = ctx->ProjectionMatrix;
  497.       GLuint i;
  498.       n = gl_userclip_polygon( ctx, n, vlist );
  499.       if (n<3)
  500.          return;
  501.       /* Transform vertices from eye to clip coordinates:  clip = Proj * eye */
  502.       for (i=0;i<n;i++) {
  503.          GLuint j = vlist[i];
  504.          TRANSFORM_POINT( VB->Clip[j], proj, VB->Eye[j] );
  505.       }
  506.    }
  507.  
  508.    /* Clip against view volume in clip coord space */
  509.    n = gl_viewclip_polygon( ctx, n, vlist );
  510.    if (n<3)
  511.       return;
  512.  
  513.    /* Transform vertices from clip to ndc to window coords.        */
  514.    /* ndc = clip / W    window = viewport_mapping(ndc)             */
  515.    /* Note that window Z values are scaled to the range of integer */
  516.    /* depth buffer values.                                         */
  517.    {
  518.       GLfloat sx = ctx->Viewport.Sx;
  519.       GLfloat tx = ctx->Viewport.Tx;
  520.       GLfloat sy = ctx->Viewport.Sy;
  521.       GLfloat ty = ctx->Viewport.Ty;
  522.       GLfloat sz = ctx->Viewport.Sz;
  523.       GLfloat tz = ctx->Viewport.Tz;
  524.       GLuint i;
  525.       for (i=0;i<n;i++) {
  526.          GLuint j = vlist[i];
  527.          GLfloat d;
  528.          ASSERT( VB->Clip[j][3] != 0.0 );
  529.          d = 1.0F / VB->Clip[j][3];
  530.          win[j][0] = VB->Clip[j][0] * d * sx + tx;
  531.          win[j][1] = VB->Clip[j][1] * d * sy + ty;
  532.          win[j][2] = VB->Clip[j][2] * d * sz + tz;
  533.       }
  534.    }
  535.  
  536.    /* Compute orientation of polygon, do cull test, offset, etc */
  537.    {
  538.       GLuint facing;   /* 0=front, 1=back */
  539.       GLfloat area = polygon_area( VB, n, vlist );
  540.  
  541.       if (area==0.0F) {
  542.          /* polygon has zero area, don't draw it */
  543.          return;
  544.       }
  545.  
  546.       facing = (area<0.0F) ^ odd_flag ^ (ctx->Polygon.FrontFace==GL_CW);
  547.  
  548.       if ((facing+1) & ctx->Polygon.CullBits) {
  549.          return;   /* culled */
  550.       }
  551.  
  552.       if (ctx->Polygon.OffsetAny) {
  553.          /* compute plane equation of polygon, apply offset */
  554.          GLuint j0 = vlist[0];
  555.          GLuint j1 = vlist[1];
  556.          GLuint j2 = vlist[2];
  557.          GLuint j3 = vlist[ (n==3) ? 0 : 3 ];
  558.          GLfloat ex = win[j1][0] - win[j3][0];
  559.          GLfloat ey = win[j1][1] - win[j3][1];
  560.          GLfloat ez = win[j1][2] - win[j3][2];
  561.          GLfloat fx = win[j2][0] - win[j0][0];
  562.          GLfloat fy = win[j2][1] - win[j0][1];
  563.          GLfloat fz = win[j2][2] - win[j0][2];
  564.          GLfloat a = ey*fz-ez*fy;
  565.          GLfloat b = ez*fx-ex*fz;
  566.          GLfloat c = ex*fy-ey*fx;
  567.          offset_polygon( ctx, a, b, c );
  568.       }
  569.  
  570.       if (ctx->Light.Model.TwoSide) {
  571.          if (facing==1 && ctx->Light.Enabled) {
  572.             /* use back color or index */
  573.             VB->Color = VB->Bcolor;
  574.             VB->Index = VB->Bindex;
  575.          }
  576.          else {
  577.             /* use front color or index */
  578.             VB->Color = VB->Fcolor;
  579.             VB->Index = VB->Findex;
  580.          }
  581.       }
  582.  
  583.       /* Render the polygon! */
  584.       if (ctx->Polygon.Unfilled) {
  585.          unfilled_polygon( ctx, n, vlist, pv, facing );
  586.       }
  587.       else {
  588.          /* Draw filled polygon as a triangle fan */
  589.          GLint i;
  590.          GLuint j0 = vlist[0];
  591.          for (i=2;i<n;i++) {
  592.             START_PROFILE
  593.             (*ctx->TriangleFunc)( ctx, j0, vlist[i-1], vlist[i], pv );
  594.             END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  595.          }
  596.       }
  597.    }
  598. }
  599.  
  600.  
  601.  
  602. /*
  603.  * Render an un-clipped triangle.
  604.  */
  605. static void render_triangle( GLcontext *ctx,
  606.                              GLuint v0, GLuint v1, GLuint v2, GLuint pv,
  607.                              GLuint odd_flag )
  608. {
  609.    struct vertex_buffer *VB = ctx->VB;
  610.    GLfloat ex, ey, fx, fy, c;
  611.    GLuint facing;  /* 0=front, 1=back */
  612.  
  613.    /* Compute orientation of triangle */
  614.    ex = VB->Win[v1][0] - VB->Win[v0][0];
  615.    ey = VB->Win[v1][1] - VB->Win[v0][1];
  616.    fx = VB->Win[v2][0] - VB->Win[v0][0];
  617.    fy = VB->Win[v2][1] - VB->Win[v0][1];
  618.    c = ex*fy-ey*fx;
  619.  
  620.    if (c==0.0F) {
  621.       /* polygon is perpindicular to view plane, don't draw it */
  622.       return;
  623.    }
  624.  
  625.    facing = (c<0.0F) ^ odd_flag ^ (ctx->Polygon.FrontFace==GL_CW);
  626.  
  627.    if ((facing+1) & ctx->Polygon.CullBits) {
  628.       return;   /* culled */
  629.    }
  630.  
  631.    if (ctx->Polygon.OffsetAny) {
  632.       /* finish computing plane equation of polygon, compute offset */
  633.       GLfloat fz = VB->Win[v2][2] - VB->Win[v0][2];
  634.       GLfloat ez = VB->Win[v1][2] - VB->Win[v0][2];
  635.       GLfloat a = ey*fz-ez*fy;
  636.       GLfloat b = ez*fx-ex*fz;
  637.       offset_polygon( ctx, a, b, c );
  638.    }
  639.  
  640.    if (ctx->Light.Model.TwoSide) {
  641.       if (facing==1 && ctx->Light.Enabled) {
  642.          /* use back color or index */
  643.          VB->Color = VB->Bcolor;
  644.          VB->Index = VB->Bindex;
  645.       }
  646.       else {
  647.          /* use front color or index */
  648.          VB->Color = VB->Fcolor;
  649.          VB->Index = VB->Findex;
  650.       }
  651.    }
  652.  
  653.    if (ctx->Polygon.Unfilled) {
  654.       GLuint vlist[3];
  655.       vlist[0] = v0;
  656.       vlist[1] = v1;
  657.       vlist[2] = v2;
  658.       unfilled_polygon( ctx, 3, vlist, pv, facing );
  659.    }
  660.    else {
  661.       START_PROFILE
  662.       (*ctx->TriangleFunc)( ctx, v0, v1, v2, pv );
  663.       END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  664.    }
  665. }
  666.  
  667.  
  668.  
  669. /*
  670.  * Render an un-clipped quadrilateral.
  671.  */
  672. static void render_quad( GLcontext *ctx,
  673.                          GLuint v0, GLuint v1, GLuint v2, GLuint v3,
  674.                          GLuint pv, GLuint odd_flag )
  675. {
  676.    struct vertex_buffer *VB = ctx->VB;
  677.    GLfloat ex, ey, fx, fy, c;
  678.    GLuint facing;  /* 0=front, 1=back */
  679.  
  680.    /* Compute polygon orientation */
  681.    ex = VB->Win[v2][0] - VB->Win[v0][0];
  682.    ey = VB->Win[v2][1] - VB->Win[v0][1];
  683.    fx = VB->Win[v3][0] - VB->Win[v1][0];
  684.    fy = VB->Win[v3][1] - VB->Win[v1][1];
  685.    c = ex*fy-ey*fx;
  686.  
  687.    if (c==0.0F) {
  688.       /* polygon is perpindicular to view plane, don't draw it */
  689.       return;
  690.    }
  691.  
  692.    facing = (c<0.0F) ^ odd_flag ^ (ctx->Polygon.FrontFace==GL_CW);
  693.  
  694.    if ((facing+1) & ctx->Polygon.CullBits) {
  695.       return;   /* culled */
  696.    }
  697.  
  698.    if (ctx->Polygon.OffsetAny) {
  699.       /* finish computing plane equation of polygon, compute offset */
  700.       GLfloat ez = VB->Win[v2][2] - VB->Win[v0][2];
  701.       GLfloat fz = VB->Win[v3][2] - VB->Win[v1][2];
  702.       GLfloat a = ey*fz-ez*fy;
  703.       GLfloat b = ez*fx-ex*fz;
  704.       offset_polygon( ctx, a, b, c );
  705.    }
  706.  
  707.    if (ctx->Light.Model.TwoSide) {
  708.       if (facing==1 && ctx->Light.Enabled) {
  709.          /* use back color or index */
  710.          VB->Color = VB->Bcolor;
  711.          VB->Index = VB->Bindex;
  712.       }
  713.       else {
  714.          /* use front color or index */
  715.          VB->Color = VB->Fcolor;
  716.          VB->Index = VB->Findex;
  717.       }
  718.    }
  719.  
  720.    /* Render the quad! */
  721.    if (ctx->Polygon.Unfilled) {
  722.       GLuint vlist[4];
  723.       vlist[0] = v0;
  724.       vlist[1] = v1;
  725.       vlist[2] = v2;
  726.       vlist[3] = v3;
  727.       unfilled_polygon( ctx, 4, vlist, pv, facing );
  728.    }
  729.    else {
  730.       START_PROFILE
  731.       (*ctx->TriangleFunc)( ctx, v0, v1, v3, pv );
  732.       (*ctx->TriangleFunc)( ctx, v1, v2, v3, pv );
  733.       END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  734.    }
  735. }
  736.  
  737.  
  738.  
  739. /*
  740.  * When the vertex buffer is full, we transform/render it.  Sometimes we
  741.  * have to copy the last vertex (or two) to the front of the vertex list
  742.  * to "continue" the primitive.  For example:  line or triangle strips.
  743.  * This function is a helper for that.
  744.  */
  745. static void copy_vertex( struct vertex_buffer *vb, GLuint dst, GLuint src )
  746. {
  747.    COPY_4V( vb->Clip[dst], vb->Clip[src] );
  748.    COPY_4V( vb->Eye[dst], vb->Eye[src] );
  749.    COPY_3V( vb->Win[dst], vb->Win[src] );
  750.    COPY_4V( vb->Fcolor[dst], vb->Fcolor[src] );
  751.    COPY_4V( vb->Bcolor[dst], vb->Bcolor[src] );
  752.    COPY_4V( vb->TexCoord[dst], vb->TexCoord[src] );
  753.    vb->Findex[dst] = vb->Findex[src];
  754.    vb->Bindex[dst] = vb->Bindex[src];
  755.    vb->Edgeflag[dst] = vb->Edgeflag[src];
  756.    vb->Unclipped[dst] = vb->Unclipped[src];
  757. }
  758.  
  759.  
  760.  
  761.  
  762. /*
  763.  * Either the vertex buffer is full (VB->Count==VB_MAX) or glEnd() has been
  764.  * called.  Render the primitives defined by the vertices and reset the
  765.  * buffer.
  766.  * Input:  alldone - GL_TRUE = caller is glEnd()
  767.  *                   GL_FALSE = calling because buffer is full.
  768.  */
  769. void gl_render_vb( GLcontext *ctx, GLboolean alldone )
  770. {
  771.    struct vertex_buffer *VB = ctx->VB;
  772.    GLuint vlist[VB_SIZE];
  773.  
  774.    switch (ctx->Primitive) {
  775.       case GL_POINTS:
  776.          START_PROFILE
  777.          (*ctx->PointsFunc)( ctx, 0, VB->Count-1 );
  778.          END_PROFILE( ctx->PointTime, ctx->PointCount, VB->Count )
  779.      VB->Count = 0;
  780.          VB->AnyClipped = GL_FALSE;
  781.      break;
  782.  
  783.       case GL_LINES:
  784.          if (VB->AnyClipped) {
  785.             GLuint i;
  786.             for (i=1;i<VB->Count;i+=2) {
  787.                if (VB->Unclipped[i-1] & VB->Unclipped[i]) {
  788.                   START_PROFILE
  789.                   (*ctx->LineFunc)( ctx, i-1, i, i );
  790.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  791.                }
  792.                else {
  793.                   render_clipped_line( ctx, i-1, i );
  794.                }
  795.                ctx->StippleCounter = 0;
  796.             }
  797.          }
  798.          else {
  799.             GLuint i;
  800.             for (i=1;i<VB->Count;i+=2) {
  801.                START_PROFILE
  802.                (*ctx->LineFunc)( ctx, i-1, i, i );
  803.                END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  804.                ctx->StippleCounter = 0;
  805.             }
  806.          }
  807.      VB->Count = 0;
  808.          VB->AnyClipped = GL_FALSE;
  809.      break;
  810.  
  811.       case GL_LINE_STRIP:
  812.          if (VB->AnyClipped) {
  813.             GLuint i;
  814.         for (i=1;i<VB->Count;i++) {
  815.                if (VB->Unclipped[i-1] & VB->Unclipped[i]) {
  816.                   START_PROFILE
  817.                   (*ctx->LineFunc)( ctx, i-1, i, i );
  818.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  819.                }
  820.                else {
  821.                   render_clipped_line( ctx, i-1, i );
  822.                }
  823.         }
  824.          }
  825.          else {
  826.             /* no clipping needed */
  827.             GLuint i;
  828.         for (i=1;i<VB->Count;i++) {
  829.                START_PROFILE
  830.                (*ctx->LineFunc)( ctx, i-1, i, i );
  831.                END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  832.             }
  833.          }
  834.          if (!alldone) {
  835.             copy_vertex( VB, 0, VB->Count-1 );  /* copy last vertex to front */
  836.             VB->Count = 1;
  837.             VB->AnyClipped = VB->Unclipped[0] ? GL_FALSE : GL_TRUE;
  838.      }
  839.          break;
  840.  
  841.       case GL_LINE_LOOP:
  842.          {
  843.             GLuint i;
  844.             if (VB->Start==0) {
  845.                i = 1;  /* start at 0th vertex */
  846.             }
  847.             else {
  848.                i = 2;  /* skip first vertex, we're saving it until glEnd */
  849.             }
  850.             while (i<VB->Count) {
  851.                if (VB->Unclipped[i-1] & VB->Unclipped[i]) {
  852.                   START_PROFILE
  853.                   (*ctx->LineFunc)( ctx, i-1, i, i );
  854.                   END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  855.                }
  856.                else {
  857.                   render_clipped_line( ctx, i-1, i );
  858.                }
  859.                i++;
  860.             }
  861.          }
  862.      if (alldone) {
  863.             if (VB->Unclipped[VB->Count-1] & VB->Unclipped[0]) {
  864.                START_PROFILE
  865.                (*ctx->LineFunc)( ctx, VB->Count-1, 0, 0 );
  866.                END_PROFILE( ctx->LineTime, ctx->LineCount, 1 )
  867.             }
  868.             else {
  869.                render_clipped_line( ctx, VB->Count-1, 0 );
  870.             }
  871.      }
  872.      else {
  873.         ASSERT(VB->Count==VB_MAX);
  874.         /* recycle the vertex list */
  875.             copy_vertex( VB, 1, VB_MAX-1 );
  876.         VB->Count = 2;
  877.             VB->AnyClipped = !VB->Unclipped[0] || !VB->Unclipped[1];
  878.      }
  879.          break;
  880.  
  881.       case GL_TRIANGLES:
  882.          if (VB->AnyClipped) {
  883.             GLuint i;
  884.             for (i=2;i<VB->Count;i+=3) {
  885.                if (VB->Unclipped[i-2] & VB->Unclipped[i-1] & VB->Unclipped[i]) {
  886.                   if (ctx->DirectTriangles) {
  887.                      START_PROFILE
  888.                      (*ctx->TriangleFunc)( ctx, i-2, i-1, i, i );
  889.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  890.                   }
  891.                   else {
  892.                      render_triangle( ctx, i-2, i-1, i, i, 0 );
  893.                   }
  894.                }
  895.                else {
  896.                   vlist[0] = i-2;
  897.                   vlist[1] = i-1;
  898.                   vlist[2] = i-0;
  899.                   render_clipped_polygon( ctx, 3, vlist, 0 );
  900.                }
  901.             }
  902.          }
  903.          else {
  904.             /* no clipping needed */
  905.             GLuint i;
  906.             if (ctx->DirectTriangles) {
  907.                for (i=2;i<VB->Count;i+=3) {
  908.                   START_PROFILE
  909.                   (*ctx->TriangleFunc)( ctx, i-2, i-1, i, i );
  910.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  911.                }
  912.             }
  913.             else {
  914.                for (i=2;i<VB->Count;i+=3) {
  915.                   render_triangle( ctx, i-2, i-1, i, i, 0 );
  916.                }
  917.             }
  918.          }
  919.      VB->Count = 0;
  920.          VB->AnyClipped = GL_FALSE;
  921.      break;
  922.  
  923.       case GL_TRIANGLE_STRIP:
  924.          if (VB->AnyClipped) {
  925.             GLuint i;
  926.             for (i=2;i<VB->Count;i++) {
  927.                if (VB->Unclipped[i-2] & VB->Unclipped[i-1] & VB->Unclipped[i]) {
  928.                   /* TODO: if direct triangle... */
  929.                   if (ctx->DirectTriangles) {
  930.                      START_PROFILE
  931.                      (*ctx->TriangleFunc)( ctx, i-2, i-1, i, i );
  932.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  933.                   }
  934.                   else {
  935.                      render_triangle( ctx, i-2, i-1, i, i, i&1 );
  936.                   }
  937.                }
  938.                else {
  939.                   vlist[0] = i-2;
  940.                   vlist[1] = i-1;
  941.                   vlist[2] = i-0;
  942.                   render_clipped_polygon( ctx, 3, vlist, i&1 );
  943.                }
  944.             }
  945.          }
  946.          else {
  947.             /* no vertices were clipped */
  948.             GLuint i;
  949.             if (ctx->DirectTriangles) {
  950.                for (i=2;i<VB->Count;i++) {
  951.                   START_PROFILE
  952.                   (*ctx->TriangleFunc)( ctx, i-2, i-1, i, i );
  953.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  954.                }
  955.             }
  956.             else {
  957.                for (i=2;i<VB->Count;i++) {
  958.                   render_triangle( ctx, i-2, i-1, i, i, i&1 );
  959.                }
  960.             }
  961.          }
  962.          if (!alldone) {
  963.             /* get ready for more vertices in this triangle strip */
  964.             copy_vertex( VB, 0, VB_MAX-2 );
  965.             copy_vertex( VB, 1, VB_MAX-1 );
  966.             VB->Count = 2;
  967.             VB->AnyClipped = !VB->Unclipped[0] || !VB->Unclipped[1];
  968.          }
  969.      break;
  970.  
  971.       case GL_TRIANGLE_FAN:
  972.          if (VB->AnyClipped) {
  973.             GLuint i;
  974.             for (i=2;i<VB->Count;i++) {
  975.                if (VB->Unclipped[0] & VB->Unclipped[i-1] & VB->Unclipped[i]) {
  976.                   if (ctx->DirectTriangles) {
  977.                      START_PROFILE
  978.                      (*ctx->TriangleFunc)( ctx, 0, i-1, i, i );
  979.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  980.                   }
  981.                   else {
  982.                      render_triangle( ctx, 0, i-1, i, i, 0 );
  983.                   }
  984.                }
  985.                else {
  986.                   vlist[0] = 0;
  987.                   vlist[1] = i-1;
  988.                   vlist[2] = i;
  989.                   render_clipped_polygon( ctx, 3, vlist, 0 );
  990.                }
  991.             }
  992.          }
  993.          else {
  994.             /* no clipping needed */
  995.             GLuint i;
  996.             if (ctx->DirectTriangles) {
  997.                for (i=2;i<VB->Count;i++) {
  998.                   START_PROFILE
  999.                   (*ctx->TriangleFunc)( ctx, 0, i-1, i, i );
  1000.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 1 )
  1001.                }
  1002.             }
  1003.             else {
  1004.                for (i=2;i<VB->Count;i++) {
  1005.                   render_triangle( ctx, 0, i-1, i, i, 0 );
  1006.                }
  1007.             }
  1008.          }
  1009.          if (!alldone) {
  1010.             /* get ready for more vertices in this triangle fan */
  1011.             copy_vertex( VB, 1, VB_MAX-1 );
  1012.             VB->Count = 2;
  1013.             VB->AnyClipped = !VB->Unclipped[0] || !VB->Unclipped[1];
  1014.      }
  1015.      break;
  1016.  
  1017.       case GL_QUADS:
  1018.          if (VB->AnyClipped) {
  1019.             GLuint i;
  1020.             for (i=3;i<VB->Count;i+=4) {
  1021.                if (  VB->Unclipped[i-3] & VB->Unclipped[i-2]
  1022.                    & VB->Unclipped[i-1] & VB->Unclipped[i]) {
  1023.                   if (ctx->DirectTriangles) {
  1024.                      START_PROFILE
  1025.                      (*ctx->TriangleFunc)( ctx, i-3, i-2, i, i );
  1026.                      (*ctx->TriangleFunc)( ctx, i-2, i-1, i, i );
  1027.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1028.                   }
  1029.                   else {
  1030.                      render_quad( ctx, i-3, i-2, i-1, i, i, 0 );
  1031.                   }
  1032.                }
  1033.                else {
  1034.                   vlist[0] = i-3;
  1035.                   vlist[1] = i-2;
  1036.                   vlist[2] = i-1;
  1037.                   vlist[3] = i-0;
  1038.                   render_clipped_polygon( ctx, 4, vlist, 0 );
  1039.                }
  1040.             }
  1041.          }
  1042.          else {
  1043.             /* no vertices were clipped */
  1044.             GLuint i;
  1045.             if (ctx->DirectTriangles) {
  1046.                for (i=3;i<VB->Count;i+=4) {
  1047.                   START_PROFILE
  1048.                   (*ctx->TriangleFunc)( ctx, i-3, i-2, i, i );
  1049.                   (*ctx->TriangleFunc)( ctx, i-2, i-1, i, i );
  1050.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1051.                }
  1052.             }
  1053.             else {
  1054.                for (i=3;i<VB->Count;i+=4) {
  1055.                   render_quad( ctx, i-3, i-2, i-1, i, i, 0 );
  1056.                }
  1057.             }
  1058.          }
  1059.      VB->Count = 0;
  1060.          VB->AnyClipped = GL_FALSE;
  1061.      break;
  1062.  
  1063.       case GL_QUAD_STRIP:
  1064.          if (VB->AnyClipped) {
  1065.             GLuint i;
  1066.             for (i=3;i<VB->Count;i+=2) {
  1067.                if (  VB->Unclipped[i-2] & VB->Unclipped[i-3]
  1068.                    & VB->Unclipped[i-1] & VB->Unclipped[i]) {
  1069.                   if (ctx->DirectTriangles) {
  1070.                      START_PROFILE
  1071.                      (*ctx->TriangleFunc)( ctx, i-2, i-3, i, i );
  1072.                      (*ctx->TriangleFunc)( ctx, i-3, i-1, i, i );
  1073.                      END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1074.                   }
  1075.                   else {
  1076.                      render_quad( ctx, i-2, i-3, i-1, i, i, 1 );
  1077.                   }
  1078.                }
  1079.                else {
  1080.                   vlist[0] = i-2;
  1081.                   vlist[1] = i-3;
  1082.                   vlist[2] = i-1;
  1083.                   vlist[3] = i-0;
  1084.                   render_clipped_polygon( ctx, 4, vlist, 1 );
  1085.                }
  1086.             }
  1087.          }
  1088.          else {
  1089.             /* no clipping needed */
  1090.             GLuint i;
  1091.             if (ctx->DirectTriangles) {
  1092.                for (i=3;i<VB->Count;i+=2) {
  1093.                   START_PROFILE
  1094.                   (*ctx->TriangleFunc)( ctx, i-2, i-3, i, i );
  1095.                   (*ctx->TriangleFunc)( ctx, i-3, i-1, i, i );
  1096.                   END_PROFILE( ctx->PolygonTime, ctx->PolygonCount, 2 )
  1097.                }
  1098.             }
  1099.             else {
  1100.                for (i=3;i<VB->Count;i+=2) {
  1101.                   render_quad( ctx, i-2, i-3, i-1, i, i, 1 );
  1102.                }
  1103.             }
  1104.          }
  1105.          if (!alldone) {
  1106.             /* get ready for more vertices in this quad strip */
  1107.             copy_vertex( VB, 0, VB_MAX-2 );
  1108.             copy_vertex( VB, 1, VB_MAX-1 );
  1109.             VB->Count = 2;
  1110.             VB->AnyClipped = !VB->Unclipped[0] || !VB->Unclipped[1];
  1111.          }
  1112.      break;
  1113.  
  1114.       case GL_POLYGON:
  1115.          if (VB->Count>2) {
  1116.             GLuint i;
  1117.             for (i=0;i<VB->Count;i++) {
  1118.                vlist[i] = i;
  1119.             }
  1120.             if (VB->AnyClipped) {
  1121.                render_clipped_polygon( ctx, VB->Count, vlist, 0 );
  1122.             }
  1123.             else {
  1124.                render_polygon( ctx, VB->Count, vlist, 0 );
  1125.             }
  1126.          }
  1127.      if (!alldone) {
  1128.             /* get ready for more vertices just like a triangle fan */
  1129.             copy_vertex( VB, 1, VB_MAX-1 );
  1130.             VB->Count = 2;
  1131.             VB->AnyClipped = !VB->Unclipped[0] || !VB->Unclipped[1];
  1132.      }
  1133.      break;
  1134.  
  1135.       default:
  1136.          /* should never get here */
  1137.      abort();
  1138.    }
  1139.  
  1140.    /* Start = first vertex which hasn't been transformed yet */
  1141.    VB->Start = VB->Count;
  1142. }
  1143.  
  1144.  
  1145.  
  1146. /*
  1147.  * Part 2 of Vertex Buffer transformation:  compute lighting, clipflags,
  1148.  * fog, texture coords, etc.
  1149.  * The function is called either by xform_vb_part1() or by glDrawArraysEXT().
  1150.  */
  1151. void gl_transform_vb_part2( GLcontext *ctx, GLboolean alldone )
  1152. {
  1153.    struct vertex_buffer *VB = ctx->VB;
  1154. #ifdef PROFILE
  1155.    GLdouble t0 = gl_time();
  1156. #endif
  1157.  
  1158.    ASSERT( VB->Count>0 );
  1159.  
  1160.    /* Lighting */
  1161.    if (ctx->Light.Enabled) {
  1162.       if (ctx->Visual->RGBAflag) {
  1163.          if (VB->MaterialChanges) {
  1164.             GLuint i;
  1165.             /* NOTE the <= here.  This is needed in case glColor/glMaterial
  1166.              * is called after the last glVertex inside a glBegin/glEnd pair.
  1167.              */
  1168.         for (i=VB->Start;i<=VB->Count;i++) {
  1169.                update_material( ctx, i );
  1170.            gl_color_shade_vertices( ctx, 1, &VB->Eye[i], &VB->Normal[i],
  1171.                                         ctx->LightTwoSide,
  1172.                                         &VB->Fcolor[i], &VB->Bcolor[i] );
  1173.         }
  1174.      }
  1175.          else {
  1176.             if (ctx->Light.Fast) {
  1177.                /* call optimized shader */
  1178.                gl_color_shade_vertices_fast( ctx, VB->Count-VB->Start,
  1179.                                              VB->Eye + VB->Start,
  1180.                                              VB->Normal + VB->Start,
  1181.                                              ctx->LightTwoSide,
  1182.                                              VB->Fcolor + VB->Start,
  1183.                                              VB->Bcolor + VB->Start );
  1184.             }
  1185.             else {
  1186.                /* call full-featured shader */
  1187.                gl_color_shade_vertices( ctx, VB->Count-VB->Start,
  1188.                                         VB->Eye + VB->Start,
  1189.                                         VB->Normal + VB->Start,
  1190.                                         ctx->LightTwoSide,
  1191.                                         VB->Fcolor + VB->Start,
  1192.                                         VB->Bcolor + VB->Start );
  1193.             }
  1194.      }
  1195.       }
  1196.       else {
  1197.          if (VB->MaterialChanges) {
  1198.             GLuint i;
  1199.             /* NOTE the <= here.  This is needed in case glColor/glMaterial
  1200.              * is called after the last glVertex inside a glBegin/glEnd pair.
  1201.              */
  1202.             for (i=VB->Start;i<=VB->Count;i++) {
  1203.                update_material( ctx, i );
  1204.                gl_index_shade_vertices( ctx, 1, &VB->Eye[i], &VB->Normal[i],
  1205.                                         ctx->LightTwoSide,
  1206.                                         &VB->Findex[i], &VB->Bindex[i] );
  1207.             }
  1208.          }
  1209.          else {
  1210.             gl_index_shade_vertices( ctx, VB->Count-VB->Start,
  1211.                                      VB->Eye + VB->Start, VB->Normal + VB->Start,
  1212.                                      ctx->LightTwoSide,
  1213.                                      VB->Findex + VB->Start, VB->Bindex + VB->Start );
  1214.          }
  1215.       }
  1216.    }
  1217.  
  1218.    /* Per-vertex fog */
  1219.    if (ctx->Fog.Enabled && ctx->Hint.Fog!=GL_NICEST) {
  1220.       if (ctx->Visual->RGBAflag) {
  1221.          /* Fog RGB colors */
  1222.          gl_fog_color_vertices( ctx, VB->Count - VB->Start,
  1223.                                 VB->Eye + VB->Start,
  1224.                                 VB->Fcolor + VB->Start );
  1225.          if (ctx->LightTwoSide) {
  1226.             gl_fog_color_vertices( ctx, VB->Count - VB->Start,
  1227.                                    VB->Eye + VB->Start,
  1228.                                    VB->Bcolor + VB->Start );
  1229.          }
  1230.       }
  1231.       else {
  1232.          /* Fog color indexes */
  1233.          gl_fog_index_vertices( ctx, VB->Count - VB->Start,
  1234.                                 VB->Eye + VB->Start,
  1235.                                 VB->Findex + VB->Start );
  1236.          if (ctx->LightTwoSide) {
  1237.             gl_fog_index_vertices( ctx, VB->Count - VB->Start,
  1238.                                    VB->Eye + VB->Start,
  1239.                                    VB->Bindex + VB->Start );
  1240.          }
  1241.       }
  1242.    }
  1243.  
  1244.    /* Generate/transform texture coords */
  1245.    if (ctx->Texture.Enabled || ctx->RenderMode==GL_FEEDBACK) {
  1246.       if (ctx->Texture.TexGenEnabled) {
  1247.          gl_texgen( ctx, VB->Count - VB->Start,
  1248.                     VB->Obj + VB->Start,
  1249.                     VB->Eye + VB->Start,
  1250.                     VB->Normal + VB->Start,
  1251.                     VB->TexCoord + VB->Start );
  1252.       }
  1253.       if (!ctx->IdentityTexMat) {
  1254.          gl_xform_texcoords_4fv( VB->Count - VB->Start,
  1255.                                  VB->TexCoord + VB->Start,
  1256.                                  ctx->TextureMatrix );
  1257.       }
  1258.    }
  1259.  
  1260.    /* Initialize clip flags */
  1261.    MEMSET( VB->Unclipped+VB->Start, GL_TRUE, VB->Count-VB->Start );
  1262.  
  1263.    if (ctx->Transform.AnyClip) {
  1264.       /* Clip against user-defined clip planes */
  1265.       GLuint p;
  1266.       for (p=0;p<MAX_CLIP_PLANES;p++) {
  1267.          if (ctx->Transform.ClipEnabled[p]) {
  1268.             GLuint i;
  1269.             GLfloat a = ctx->Transform.ClipEquation[p][0];
  1270.             GLfloat b = ctx->Transform.ClipEquation[p][1];
  1271.             GLfloat c = ctx->Transform.ClipEquation[p][2];
  1272.             GLfloat d = ctx->Transform.ClipEquation[p][3];
  1273.             for (i=VB->Start;i<VB->Count;i++) {
  1274.                GLfloat dot = VB->Eye[i][0] * a + VB->Eye[i][1] * b
  1275.                            + VB->Eye[i][2] * c + VB->Eye[i][3] * d;
  1276.                if (dot < 0.0F) {
  1277.                   VB->Unclipped[i] = GL_FALSE;
  1278.                   VB->AnyClipped = GL_TRUE;
  1279.                }
  1280.             }
  1281.          }
  1282.       }
  1283.    }
  1284.  
  1285.    /* Transform vertices from eye to clip coords */
  1286.    /* Even transform clipped vertices because it's usually faster. */
  1287.    gl_xform_points_4fv( VB->Count-VB->Start, VB->Clip+VB->Start,
  1288.                         ctx->ProjectionMatrix, VB->Eye+VB->Start );
  1289.  
  1290.    /*
  1291.     * Combined clip testing with clip-to-window coordinate mapping.
  1292.     */
  1293.    {
  1294.       GLfloat sx = ctx->Viewport.Sx;
  1295.       GLfloat tx = ctx->Viewport.Tx;
  1296.       GLfloat sy = ctx->Viewport.Sy;
  1297.       GLfloat ty = ctx->Viewport.Ty;
  1298.       GLfloat sz = ctx->Viewport.Sz;
  1299.       GLfloat tz = ctx->Viewport.Tz;
  1300.       GLuint i, start = VB->Start, n = VB->Count;
  1301.       for (i=start;i<n;i++) {
  1302.          GLfloat clipx = VB->Clip[i][0], clipy = VB->Clip[i][1];
  1303.          GLfloat clipz = VB->Clip[i][2], clipw = VB->Clip[i][3];
  1304.          if (clipx > clipw || clipx < -clipw ||
  1305.              clipy > clipw || clipy < -clipw ||
  1306.              clipz > clipw || clipz < -clipw ) {
  1307.             /* vertex is clipped */
  1308.             VB->Unclipped[i] = GL_FALSE;
  1309.             VB->AnyClipped = GL_TRUE;
  1310.          }
  1311.          else {
  1312.             /* vertex not clipped */
  1313.             GLfloat d = 1.0F / clipw;
  1314.             VB->Win[i][0] = clipx * d * sx + tx;
  1315.             VB->Win[i][1] = clipy * d * sy + ty;
  1316.             VB->Win[i][2] = clipz * d * sz + tz;
  1317.          }
  1318.       }
  1319.    }
  1320.  
  1321. #ifdef PROFILE
  1322.    ctx->VertexTime += gl_time() - t0;
  1323.    ctx->VertexCount += VB->Count - VB->Start;
  1324. #endif
  1325. }
  1326.  
  1327.  
  1328.  
  1329. /*
  1330.  * When the Vertex Buffer is full, this function transforms all the
  1331.  * vertices and normals then calls xform_vb_part2()...
  1332.  */
  1333. void gl_transform_vb_part1( GLcontext *ctx, GLboolean alldone )
  1334. {
  1335.    struct vertex_buffer *VB = ctx->VB;
  1336. #ifdef PROFILE
  1337.    GLdouble t0 = gl_time();
  1338. #endif
  1339.  
  1340.    ASSERT( VB->Count>0 );
  1341.  
  1342.    /* Transform vertexes from object to eye coords */
  1343.    gl_xform_points_4fv( VB->Count-VB->Start, VB->Eye+VB->Start,
  1344.                         ctx->ModelViewMatrix, VB->Obj+VB->Start );
  1345.  
  1346.    /* Transform normals from object to eye coords */
  1347.    if (ctx->NeedNormals) {
  1348.       gl_xform_normals_3fv( VB->Count-VB->Start,
  1349.                             VB->Normal+VB->Start, ctx->ModelViewInv,
  1350.                             VB->Normal+VB->Start, ctx->Transform.Normalize );
  1351.    }
  1352.  
  1353. #ifdef PROFILE
  1354.    ctx->VertexTime += gl_time() - t0;
  1355. #endif
  1356.  
  1357.    /* lighting, project, etc */
  1358.    gl_transform_vb_part2( ctx, alldone );
  1359.  
  1360.    /* Render the primitives */
  1361.    gl_render_vb( ctx, alldone );
  1362. }
  1363.  
  1364.  
  1365.  
  1366. /**********************************************************************/
  1367. /**** Vertex functions.  These are called via ctx->Exec.Vertex4f() ****/
  1368. /**********************************************************************/
  1369.  
  1370. /*
  1371.  * Save a glVertex call into a display list AND execute it.
  1372.  */
  1373. void gl_save_and_execute_vertex( GLcontext *ctx,
  1374.                                  GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1375. {
  1376.    struct vertex_buffer *VB = ctx->VB;
  1377.    GLuint count = VB->Count;  /* copy to local var to encourage optimization */
  1378.  
  1379.    /* Put vertex into display list */
  1380.    gl_save_Vertex4f( ctx, x, y, z, w );
  1381.  
  1382.    /* Exectue vertex command */
  1383.    ASSIGN_4V( VB->Obj[count], x, y, z, w );
  1384.    if (ctx->Visual->RGBAflag) {
  1385.       if (ctx->Light.Enabled) {
  1386.          /* need normal vector, vertex color is computed from material */
  1387.          COPY_3V( VB->Normal[count], ctx->Current.Normal );
  1388.       }
  1389.       else {
  1390.          /* not lighting, need vertex color */
  1391.          GLint shift = ctx->ColorShift;
  1392.          VB->Fcolor[count][0] = ctx->Current.IntColor[0] << shift;
  1393.          VB->Fcolor[count][1] = ctx->Current.IntColor[1] << shift;
  1394.          VB->Fcolor[count][2] = ctx->Current.IntColor[2] << shift;
  1395.          VB->Fcolor[count][3] = ctx->Current.IntColor[3] << shift;
  1396.       }
  1397.       if (ctx->Texture.Enabled) {
  1398.          COPY_4V( VB->TexCoord[count], ctx->Current.TexCoord );
  1399.       }
  1400.    }
  1401.    else {
  1402.       if (ctx->Light.Enabled) {
  1403.          /* need normal vector, vertex color index computed from material*/
  1404.          COPY_3V( VB->Normal[count], ctx->Current.Normal );
  1405.       }
  1406.       else {
  1407.          /* not lighting, new vertex color index */
  1408.          VB->Findex[count] = ctx->Current.Index;
  1409.       }
  1410.    }
  1411.    VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  1412.  
  1413.    count++;
  1414.    VB->Count = count;
  1415.    if (count==VB_MAX) {
  1416.       gl_transform_vb_part1( ctx, GL_FALSE );
  1417.    }
  1418. }
  1419.  
  1420.  
  1421. /*
  1422.  * Used when in feedback mode.
  1423.  */
  1424. static void vertex_feedback( GLcontext *ctx,
  1425.                              GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1426. {
  1427.    struct vertex_buffer *VB = ctx->VB;
  1428.    GLuint count = VB->Count;
  1429.    GLint shift = ctx->ColorShift;
  1430.  
  1431.    /* vertex */
  1432.    ASSIGN_4V( VB->Obj[count], x, y, z, w );
  1433.  
  1434.    /* color */
  1435.    VB->Fcolor[count][0] = ctx->Current.IntColor[0] << shift;
  1436.    VB->Fcolor[count][1] = ctx->Current.IntColor[1] << shift;
  1437.    VB->Fcolor[count][2] = ctx->Current.IntColor[2] << shift;
  1438.    VB->Fcolor[count][3] = ctx->Current.IntColor[3] << shift;
  1439.  
  1440.    /* index */
  1441.    VB->Findex[count] = ctx->Current.Index;
  1442.  
  1443.    /* normal */
  1444.    COPY_3V( VB->Normal[count], ctx->Current.Normal );
  1445.  
  1446.    /* texcoord */
  1447.    COPY_4V( VB->TexCoord[count], ctx->Current.TexCoord );
  1448.  
  1449.    /* edgeflag */
  1450.    VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  1451.  
  1452.    count++;
  1453.    VB->Count = count;
  1454.    if (count==VB_MAX) {
  1455.       gl_transform_vb_part1( ctx, GL_FALSE );
  1456.    }
  1457. }
  1458.  
  1459.  
  1460. /* RGB, lit, textured vertex */
  1461. static void vertex_normal_texture( GLcontext *ctx,
  1462.                                    GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1463. {
  1464.    struct vertex_buffer *VB = ctx->VB;
  1465.    GLuint count = VB->Count;
  1466.  
  1467.    ASSIGN_4V( VB->Obj[count], x, y, z, w );
  1468.    COPY_3V( VB->Normal[count], ctx->Current.Normal );
  1469.    COPY_4V( VB->TexCoord[count], ctx->Current.TexCoord );
  1470.    VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  1471.  
  1472.    count++;
  1473.    VB->Count = count;
  1474.    if (count==VB_MAX) {
  1475.       gl_transform_vb_part1( ctx, GL_FALSE );
  1476.    }
  1477. }
  1478.  
  1479.  
  1480. /* RGB or CI, lit, untextured vertex */
  1481. static void vertex_normal( GLcontext *ctx,
  1482.                            GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1483. {
  1484.    struct vertex_buffer *VB = ctx->VB;
  1485.    GLuint count = VB->Count;
  1486.  
  1487.    ASSIGN_4V( VB->Obj[count], x, y, z, w );
  1488.    COPY_3V( VB->Normal[count], ctx->Current.Normal );
  1489.    VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  1490.  
  1491.    count++;
  1492.    VB->Count = count;
  1493.    if (count==VB_MAX) {
  1494.       gl_transform_vb_part1( ctx, GL_FALSE );
  1495.    }
  1496. }
  1497.  
  1498.  
  1499. /* RGB, unlit, textured vertex */
  1500. static void vertex_texture( GLcontext *ctx,
  1501.                             GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1502. {
  1503.    struct vertex_buffer *VB = ctx->VB;
  1504.    GLuint count = VB->Count;
  1505.    GLint shift = ctx->ColorShift;
  1506.  
  1507.    ASSIGN_4V( VB->Obj[count], x, y, z, w );
  1508.    VB->Fcolor[count][0] = ctx->Current.IntColor[0] << shift;
  1509.    VB->Fcolor[count][1] = ctx->Current.IntColor[1] << shift;
  1510.    VB->Fcolor[count][2] = ctx->Current.IntColor[2] << shift;
  1511.    VB->Fcolor[count][3] = ctx->Current.IntColor[3] << shift;
  1512.    COPY_4V( VB->TexCoord[count], ctx->Current.TexCoord );
  1513.    VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  1514.  
  1515.    count++;
  1516.    VB->Count = count;
  1517.    if (count==VB_MAX) {
  1518.       gl_transform_vb_part1( ctx, GL_FALSE );
  1519.    }
  1520. }
  1521.  
  1522.  
  1523. /* RGB, unlit, untextured vertex */
  1524. static void vertex_color( GLcontext *ctx,
  1525.                           GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1526. {
  1527.    struct vertex_buffer *VB = ctx->VB;
  1528.    GLuint count = VB->Count;
  1529.    GLint shift = ctx->ColorShift;
  1530.  
  1531.    ASSIGN_4V( VB->Obj[count], x, y, z, w );
  1532.    VB->Fcolor[count][0] = ctx->Current.IntColor[0] << shift;
  1533.    VB->Fcolor[count][1] = ctx->Current.IntColor[1] << shift;
  1534.    VB->Fcolor[count][2] = ctx->Current.IntColor[2] << shift;
  1535.    VB->Fcolor[count][3] = ctx->Current.IntColor[3] << shift;
  1536.    VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  1537.  
  1538.    count++;
  1539.    VB->Count = count;
  1540.    if (count==VB_MAX) {
  1541.       gl_transform_vb_part1( ctx, GL_FALSE );
  1542.    }
  1543. }
  1544.  
  1545.  
  1546. /* CI, unlit vertex */
  1547. static void vertex_index( GLcontext *ctx,
  1548.                           GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1549. {
  1550.    struct vertex_buffer *VB = ctx->VB;
  1551.    GLuint count = VB->Count;
  1552.  
  1553.    ASSIGN_4V( VB->Obj[count], x, y, z, w );
  1554.    VB->Findex[count] = ctx->Current.Index;
  1555.    VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  1556.  
  1557.    count++;
  1558.    VB->Count = count;
  1559.    if (count==VB_MAX) {
  1560.       gl_transform_vb_part1( ctx, GL_FALSE );
  1561.    }
  1562. }
  1563.  
  1564.  
  1565. /*
  1566.  * Called when outside glBegin/glEnd, raises an error.
  1567.  */
  1568. void gl_nop_vertex( GLcontext *ctx,
  1569.                     GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1570. {
  1571.    gl_error( ctx, GL_INVALID_OPERATION, "glVertex" );
  1572. }
  1573.  
  1574.  
  1575.  
  1576. /*
  1577.  * This function examines the current GL state and sets the
  1578.  * ctx->Exec.Vertex4f pointer to point at the appropriate vertex function.
  1579.  */
  1580. void gl_set_vertex_function( GLcontext *ctx )
  1581. {
  1582.    ASSERT( !INSIDE_BEGIN_END(ctx) );
  1583.    if (ctx->RenderMode==GL_FEEDBACK) {
  1584.       ctx->Exec.Vertex4f = vertex_feedback;
  1585.    }
  1586.    else {
  1587.       if (ctx->Visual->RGBAflag) {
  1588.          if (ctx->Light.Enabled) {
  1589.             if (ctx->Texture.Enabled) {
  1590.                ctx->Exec.Vertex4f = vertex_normal_texture;
  1591.             }
  1592.             else {
  1593.                ctx->Exec.Vertex4f = vertex_normal;
  1594.             }
  1595.          }
  1596.          else {
  1597.             /* not lighting, need vertex color */
  1598.             if (ctx->Texture.Enabled) {
  1599.                ctx->Exec.Vertex4f = vertex_texture;
  1600.             }
  1601.             else {
  1602.                ctx->Exec.Vertex4f = vertex_color;
  1603.             }
  1604.          }
  1605.       }
  1606.       else {
  1607.          /* color index mode */
  1608.          if (ctx->Light.Enabled) {
  1609.             ctx->Exec.Vertex4f = vertex_normal;
  1610.          }
  1611.          else {
  1612.             ctx->Exec.Vertex4f = vertex_index;
  1613.          }
  1614.       }
  1615.    }
  1616.  
  1617.    if (!ctx->CompileFlag) {
  1618.       ctx->API.Vertex4f = ctx->Exec.Vertex4f;
  1619.    }
  1620. }
  1621.  
  1622.  
  1623.  
  1624. /*
  1625.  * Process a vertex produced by an evaluator.
  1626.  * Input:  vertex - the X,Y,Z,W vertex
  1627.  *         normal - normal vector
  1628.  *         color - 4 integer color components
  1629.  *         index - color index
  1630.  *         texcoord - texture coordinate
  1631.  */
  1632. void gl_eval_vertex( GLcontext *ctx,
  1633.                      const GLfloat vertex[4], const GLfloat normal[3],
  1634.              const GLint color[4], GLuint index,
  1635.                      const GLfloat texcoord[4] )
  1636. {
  1637.    struct vertex_buffer *VB = ctx->VB;
  1638.    GLuint count = VB->Count;  /* copy to local var to encourage optimization */
  1639.    GLint shift = ctx->ColorShift;
  1640.  
  1641.    COPY_4V( VB->Obj[count], vertex );
  1642.    COPY_3V( VB->Normal[count], normal );
  1643.    VB->Fcolor[count][0] = color[0] << shift;
  1644.    VB->Fcolor[count][1] = color[1] << shift;
  1645.    VB->Fcolor[count][2] = color[2] << shift;
  1646.    VB->Fcolor[count][3] = color[3] << shift;
  1647. #ifdef GL_VERSION_1_1
  1648.    if (ctx->Light.ColorMaterialEnabled
  1649.        && (ctx->Eval.Map1Color4 || ctx->Eval.Map1Color4)) {
  1650.       GLfloat fcolor[4];
  1651.       fcolor[0] = color[0] * ctx->Visual->InvRedScale;
  1652.       fcolor[1] = color[1] * ctx->Visual->InvGreenScale;
  1653.       fcolor[2] = color[2] * ctx->Visual->InvBlueScale;
  1654.       fcolor[3] = color[3] * ctx->Visual->InvAlphaScale;
  1655.       gl_set_material( ctx, ctx->Light.ColorMaterialBitmask, fcolor );
  1656.    }
  1657. #endif
  1658.    VB->Findex[count] = index;
  1659.    COPY_4V( VB->TexCoord[count], texcoord );
  1660.    VB->Edgeflag[count] = ctx->Current.EdgeFlag;
  1661.  
  1662.    count++;
  1663.    VB->Count = count;
  1664.    if (count==VB_MAX) {
  1665.       gl_transform_vb_part1( ctx, GL_FALSE );
  1666.    }
  1667. }
  1668.  
  1669.  
  1670.  
  1671.  
  1672. void gl_RasterPos4f( GLcontext *ctx,
  1673.                      GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1674. {
  1675.    GLfloat v[4], eye[4], clip[4], ndc[3], d;
  1676.  
  1677.    v[0] = x;
  1678.    v[1] = y;
  1679.    v[2] = z;
  1680.    v[3] = w;
  1681.  
  1682.    /* transform v to eye coords:  eye = ModelView * v */
  1683.    TRANSFORM_POINT( eye, ctx->ModelViewMatrix, v );
  1684.  
  1685.    /* raster color */
  1686.    if (ctx->Light.Enabled) {
  1687.       GLfloat eyenorm[3];
  1688.       if (!ctx->ModelViewInvValid) {
  1689.      gl_compute_modelview_inverse(ctx);
  1690.       }
  1691.       TRANSFORM_NORMAL( eyenorm[0], eyenorm[1], eyenorm[2], ctx->Current.Normal,
  1692.                         ctx->ModelViewInv );
  1693.       ctx->ColorShift = 0;  /* Colors only shifted when smooth shading */
  1694.       if (ctx->Visual->RGBAflag) {
  1695.          GLfixed color[4];  /* not really fixed point but integers */
  1696.          GLfixed bcolor[4]; /* not used, dummy arg */
  1697.          gl_color_shade_vertices( ctx, 1, &eye, &eyenorm, 0, &color, &bcolor );
  1698.          ctx->Current.RasterColor[0] = color[0] * ctx->Visual->InvRedScale;
  1699.          ctx->Current.RasterColor[1] = color[1] * ctx->Visual->InvGreenScale;
  1700.          ctx->Current.RasterColor[2] = color[2] * ctx->Visual->InvBlueScale;
  1701.          ctx->Current.RasterColor[3] = color[3] * ctx->Visual->InvAlphaScale;
  1702.       }
  1703.       else {
  1704.          GLuint dummy;
  1705.      gl_index_shade_vertices( ctx, 1, &eye, &eyenorm, 0,
  1706.                                   &ctx->Current.RasterIndex, &dummy );
  1707.       }
  1708.    }
  1709.    else {
  1710.       /* use current color or index */
  1711.       if (ctx->Visual->RGBAflag) {
  1712.          ctx->Current.RasterColor[0] = ctx->Current.IntColor[0]
  1713.                                        * ctx->Visual->InvRedScale;
  1714.          ctx->Current.RasterColor[1] = ctx->Current.IntColor[1]
  1715.                                        * ctx->Visual->InvGreenScale;
  1716.          ctx->Current.RasterColor[2] = ctx->Current.IntColor[2]
  1717.                                        * ctx->Visual->InvBlueScale;
  1718.          ctx->Current.RasterColor[3] = ctx->Current.IntColor[3]
  1719.                                        * ctx->Visual->InvAlphaScale;
  1720.       }
  1721.       else {
  1722.      ctx->Current.RasterIndex = ctx->Current.Index;
  1723.       }
  1724.    }
  1725.  
  1726.    /* clip to user clipping planes */
  1727.    if (gl_userclip_point(ctx, eye)==0) {
  1728.       ctx->Current.RasterPosValid = GL_FALSE;
  1729.       return;
  1730.    }
  1731.  
  1732.    /* compute raster distance */
  1733.    ctx->Current.RasterDistance = (GLfloat)
  1734.                       sqrt( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );
  1735.  
  1736.    /* apply projection matrix:  clip = Proj * eye */
  1737.    TRANSFORM_POINT( clip, ctx->ProjectionMatrix, eye );
  1738.  
  1739.    /* clip to view volume */
  1740.    if (gl_viewclip_point( clip )==0) {
  1741.       ctx->Current.RasterPosValid = GL_FALSE;
  1742.       return;
  1743.    }
  1744.  
  1745.    /* ndc = clip / W */
  1746.    ASSERT( clip[3]!=0.0 );
  1747.    d = 1.0F / clip[3];
  1748.    ndc[0] = clip[0] * d;
  1749.    ndc[1] = clip[1] * d;
  1750.    ndc[2] = clip[2] * d;
  1751.  
  1752.    ctx->Current.RasterPos[0] = ndc[0] * ctx->Viewport.Sx + ctx->Viewport.Tx;
  1753.    ctx->Current.RasterPos[1] = ndc[1] * ctx->Viewport.Sy + ctx->Viewport.Ty;
  1754.    ctx->Current.RasterPos[2] = (ndc[2] * ctx->Viewport.Sz + ctx->Viewport.Tz)
  1755.                                / DEPTH_SCALE;
  1756.    ctx->Current.RasterPos[3] = clip[3];
  1757.    ctx->Current.RasterPosValid = GL_TRUE;
  1758.  
  1759.    /* FOG??? */
  1760.  
  1761.    if (ctx->Texture.Enabled) {
  1762.       COPY_4V( ctx->Current.RasterTexCoord, ctx->Current.TexCoord );
  1763.    }
  1764.  
  1765.    if (ctx->RenderMode==GL_SELECT) {
  1766.       gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
  1767.    }
  1768.  
  1769. }
  1770.  
  1771.  
  1772.  
  1773.  
  1774. void gl_windowpos( GLcontext *ctx, GLfloat x, GLfloat y, GLfloat z, GLfloat w )
  1775. {
  1776.  
  1777.    /* set raster position */
  1778.    ctx->Current.RasterPos[0] = x;
  1779.    ctx->Current.RasterPos[1] = y;
  1780.    ctx->Current.RasterPos[2] = CLAMP( z, 0.0F, 1.0F );
  1781.    ctx->Current.RasterPos[3] = w;
  1782.  
  1783.    ctx->Current.RasterPosValid = GL_TRUE;
  1784.  
  1785.    /* raster color */
  1786.    if (ctx->Light.Enabled) {
  1787.       GLfloat eye[4];
  1788.       GLfloat eyenorm[3];
  1789.       COPY_4V( eye, ctx->Current.RasterPos );
  1790.       if (!ctx->ModelViewInvValid) {
  1791.      gl_compute_modelview_inverse(ctx);
  1792.       }
  1793.       TRANSFORM_NORMAL( eyenorm[0], eyenorm[1], eyenorm[2], ctx->Current.Normal,
  1794.                         ctx->ModelViewInv );
  1795.       ctx->ColorShift = 0;  /* Colors only shifted when smooth shading */
  1796.       if (ctx->Visual->RGBAflag) {
  1797.          GLfixed color[4];  /* not really fixed point but integers */
  1798.          GLfixed bcolor[4]; /* not used, dummy arg */
  1799.          gl_color_shade_vertices( ctx, 1, &eye, &eyenorm, 0, &color, &bcolor );
  1800.          ctx->Current.RasterColor[0] = (GLfloat) color[0] * ctx->Visual->InvRedScale;
  1801.          ctx->Current.RasterColor[1] = (GLfloat) color[1] * ctx->Visual->InvGreenScale;
  1802.          ctx->Current.RasterColor[2] = (GLfloat) color[2] * ctx->Visual->InvBlueScale;
  1803.          ctx->Current.RasterColor[3] = (GLfloat) color[3] * ctx->Visual->InvAlphaScale;
  1804.       }
  1805.       else {
  1806.          GLuint dummy;
  1807.      gl_index_shade_vertices( ctx, 1, &eye, &eyenorm, 0,
  1808.                                   &ctx->Current.RasterIndex, &dummy );
  1809.       }
  1810.    }
  1811.    else {
  1812.       /* use current color or index */
  1813.       if (ctx->Visual->RGBAflag) {
  1814.          ctx->Current.RasterColor[0] = ctx->Current.IntColor[0] * ctx->Visual->InvRedScale;
  1815.          ctx->Current.RasterColor[1] = ctx->Current.IntColor[1] * ctx->Visual->InvGreenScale;
  1816.          ctx->Current.RasterColor[2] = ctx->Current.IntColor[2] * ctx->Visual->InvBlueScale;
  1817.          ctx->Current.RasterColor[3] = ctx->Current.IntColor[3] * ctx->Visual->InvAlphaScale;
  1818.       }
  1819.       else {
  1820.      ctx->Current.RasterIndex = ctx->Current.Index;
  1821.       }
  1822.    }
  1823.  
  1824.    ctx->Current.RasterDistance = 0.0;
  1825.  
  1826.    if (ctx->Texture.Enabled) {
  1827.       COPY_4V( ctx->Current.RasterTexCoord, ctx->Current.TexCoord );
  1828.    }
  1829.  
  1830.    if (ctx->RenderMode==GL_SELECT) {
  1831.       gl_update_hitflag( ctx, ctx->Current.RasterPos[2] );
  1832.    }
  1833. }
  1834.  
  1835.  
  1836.  
  1837.  
  1838. #ifdef PROFILE
  1839. static GLdouble begin_time;
  1840. #endif
  1841.  
  1842.  
  1843. void gl_Begin( GLcontext *ctx, GLenum p )
  1844. {
  1845.    struct vertex_buffer *VB = ctx->VB;
  1846.    struct pixel_buffer *PB = ctx->PB;
  1847. #ifdef PROFILE
  1848.    begin_time = gl_time();
  1849. #endif
  1850.  
  1851.    if (INSIDE_BEGIN_END(ctx)) {
  1852.       gl_error( ctx, GL_INVALID_OPERATION, "glBegin" );
  1853.       return;
  1854.    }
  1855.    if (!ctx->ModelViewInvValid) {
  1856.       gl_compute_modelview_inverse(ctx);
  1857.    }
  1858.    if (ctx->NewState) {
  1859.       gl_update_state(ctx);
  1860.    }
  1861.    else if (ctx->Exec.Vertex4f==gl_nop_vertex) {
  1862.       gl_set_vertex_function(ctx);
  1863.    }
  1864.  
  1865.    if (ctx->Driver.Begin) {
  1866.       (*ctx->Driver.Begin)( ctx, p );
  1867.    }
  1868.  
  1869.    ctx->Primitive = p;
  1870.    VB->Start = VB->Count = 0;
  1871.    VB->AnyClipped = GL_FALSE;
  1872.  
  1873.    VB->MonoColor = ctx->MonoPixels;
  1874.    if (VB->MonoColor) {
  1875.       /* All pixels generated are likely to be the same color so have
  1876.        * the device driver set the "monocolor" now.
  1877.        */
  1878.       if (ctx->Visual->RGBAflag) {
  1879.          GLubyte r = ctx->Current.IntColor[0];
  1880.          GLubyte g = ctx->Current.IntColor[1];
  1881.          GLubyte b = ctx->Current.IntColor[2];
  1882.          GLubyte a = ctx->Current.IntColor[3];
  1883.          (*ctx->Driver.Color)( ctx, r, g, b, a );
  1884.       }
  1885.       else {
  1886.          (*ctx->Driver.Index)( ctx, ctx->Current.Index );
  1887.       }
  1888.    }
  1889.  
  1890.    /*
  1891.     * If flat shading, save integer vertex colors
  1892.     * else, save fixed-point (scaled) vertex colors
  1893.     */
  1894.    ctx->ColorShift = (ctx->Light.ShadeModel==GL_FLAT) ? 0 : FIXED_SHIFT;
  1895.  
  1896.    /* By default use front color/index.  Two-sided lighting may override. */
  1897.    VB->Color = VB->Fcolor;
  1898.    VB->Index = VB->Findex;
  1899.  
  1900.    switch (ctx->Primitive) {
  1901.       case GL_POINTS:
  1902.      ctx->LightTwoSide = 0;
  1903.      PB_INIT( PB, GL_POINT );
  1904.      break;
  1905.       case GL_LINES:
  1906.       case GL_LINE_STRIP:
  1907.       case GL_LINE_LOOP:
  1908.      ctx->LightTwoSide = 0;
  1909.      ctx->StippleCounter = 0;
  1910.      PB_INIT( PB, GL_LINE );
  1911.          break;
  1912.       case GL_TRIANGLES:
  1913.       case GL_TRIANGLE_STRIP:
  1914.       case GL_TRIANGLE_FAN:
  1915.       case GL_QUADS:
  1916.       case GL_QUAD_STRIP:
  1917.       case GL_POLYGON:
  1918.      ctx->LightTwoSide = (GLuint) ctx->Light.Model.TwoSide;
  1919.      PB_INIT( PB, GL_POLYGON );
  1920.          break;
  1921.       default:
  1922.      gl_error( ctx, GL_INVALID_ENUM, "glBegin" );
  1923.      ctx->Primitive = GL_BITMAP;
  1924.    }
  1925. }
  1926.  
  1927.  
  1928.  
  1929. void gl_End( GLcontext *ctx )
  1930. {
  1931.    struct pixel_buffer *PB = ctx->PB;
  1932.    struct vertex_buffer *VB = ctx->VB;
  1933.  
  1934.    if (ctx->Primitive==GL_BITMAP) {
  1935.       /* glEnd without glBegin */
  1936.       gl_error( ctx, GL_INVALID_OPERATION, "glEnd" );
  1937.       return;
  1938.    }
  1939.  
  1940.    if (VB->Count>VB->Start) {
  1941.       gl_transform_vb_part1( ctx, GL_TRUE );
  1942.    }
  1943.    if (PB->count>0) {
  1944.       gl_flush_pb(ctx);
  1945.    }
  1946.    PB->primitive = ctx->Primitive = GL_BITMAP;  /* Default mode */
  1947.    VB->MaterialChanges = GL_FALSE;
  1948.  
  1949.    if (ctx->Driver.End) {
  1950.       (*ctx->Driver.End)(ctx);
  1951.    }
  1952.  
  1953. #ifdef PROFILE
  1954.    ctx->BeginEndTime += gl_time() - begin_time;
  1955.    ctx->BeginEndCount++;
  1956. #endif
  1957. }
  1958.  
  1959.